<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>发布订阅模式</title>
</head>
<body>
<h6>发布订阅模式</h6>
<script>
    class EventBus{
        constructor() {
            this.eventMap = new Map();
        }
        on(type, fn) {
            if(!this.eventMap.has(type)) {
                this.eventMap.set(type, [fn])
            } else {
                this.eventMap.get(type).push(fn)
            }
        }
        emit(type, args) {
            const fns = this.eventMap.get(type);
            Array.isArray(fns) && fns.length && fns.forEach(fn => fn(args))
        }
        off(type, fn) {
            const fns = this.eventMap.get(type);
            const filterFns = fns.filter(item => {
                return item !== fn
            });
            this.eventMap.set(type, filterFns)
        }
        once(type, fn){
            // 单独声明一个回调函数，用完后删除
            const callback = (...args) => {
                fn(...args);
                this.off(type, callback)
            }
            this.on(type, callback)
        }
    }
    const bus = new EventBus();
    const fn = function(args) {
        console.log(args)
    }
    bus.on('test', fn) // 订阅
    bus.on('test', fn) // 订阅
    bus.once('test', fn) // 订阅一次
    bus.emit('test', 'hello world') // 发布
    bus.emit('test', 'hello world11111') // 发布
    bus.off('test', fn) // 取消订阅
    console.log(bus);
</script>
</body>
</html>
